/*
 * MIT License
 *
 * Copyright (c) 2023 北京凯特伟业科技有限公司
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 * SOFTWARE.
 */
package com.je.rbac.rpc;

import com.google.common.base.Joiner;
import com.google.common.base.Splitter;
import com.google.common.base.Strings;
import com.je.common.base.DynaBean;
import com.je.common.base.service.MetaService;
import com.je.common.base.service.rpc.BeanService;
import com.je.common.base.util.ArrayUtils;
import com.je.common.base.util.StringUtil;
import com.je.common.base.util.TreeUtil;
import com.je.core.entity.extjs.JSONTreeNode;
import com.je.ibatis.extension.conditions.ConditionsWrapper;
import com.je.rbac.exception.CompanyException;
import com.je.rbac.service.IconType;
import com.je.rbac.service.company.RbacDepartmentService;
import org.apache.commons.lang.StringUtils;
import org.apache.servicecomb.provider.pojo.RpcSchema;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;

@RpcSchema(schemaId = "companyRpcService")
public class CompanyRpcServiceImpl implements CompanyRpcService {

    @Autowired
    private MetaService metaService;
    @Autowired
    private BeanService beanService;
    @Autowired
    private RbacDepartmentService rbacDepartmentService;

    @Override
    public List<DynaBean> findAll() {
        return metaService.select("JE_RBAC_COMPANY", ConditionsWrapper.builder().eq("SY_STATUS","1").apply("ORDER BY SY_TREEORDERINDEX ASC,SY_ORDERINDEX ASC"));
    }

    @Override
    public DynaBean findById(String id) {
        return metaService.selectOne("JE_RBAC_COMPANY", ConditionsWrapper.builder().eq("JE_RBAC_COMPANY_ID", id));
    }

    @Override
    public DynaBean findByCode(String code) {
        return metaService.selectOne("JE_RBAC_COMPANY", ConditionsWrapper.builder().eq("COMPANY_CODE", code));
    }

    @Override
    public DynaBean findByName(String name) {
        return metaService.selectOne("JE_RBAC_COMPANY", ConditionsWrapper.builder().eq("COMPANY_NAME", name));
    }

    @Override
    public DynaBean findParent(String id) {
        DynaBean currentCompanyBean = findById(id);
        if (currentCompanyBean == null) {
            return null;
        }
        String parentId = currentCompanyBean.getStr("SY_PARENT");
        if (Strings.isNullOrEmpty(parentId)) {
            return null;
        }
        return findById(parentId);
    }

    @Override
    public DynaBean findAncestors(String id) {
        return metaService.selectOne("JE_RBAC_COMPANY", ConditionsWrapper.builder().likeLeft("SY_PATH", id).eq("SY_PARENT", "ROOT"));
    }

    @Override
    public List<DynaBean> findNextChildren(String id, boolean containMe) {
        return metaService.select("JE_RBAC_COMPANY", ConditionsWrapper.builder().eq("SY_PARENT", id)
                .or(containMe).eq(containMe, "JE_RBAC_COMPANY_ID", id));
    }

    @Override
    public List<DynaBean> findAllChildren(String id, boolean containMe) {
        return metaService.select("JE_RBAC_COMPANY", ConditionsWrapper.builder().likeRight("SY_PATH", id)
                .or(containMe).eq(containMe, "JE_RBAC_COMPANY_ID", id));
    }

    @Override
    public List<DynaBean> findByManagerId(String managerId) {
        return metaService.select("JE_RBAC_COMPANY", ConditionsWrapper.builder().like("COMPANY_MANAGER_ID", "%" + managerId + "%"));
    }

    @Override
    public List<DynaBean> findByMajorId(String majorId) {
        return metaService.select("JE_RBAC_COMPANY", ConditionsWrapper.builder().eq("COMPANY_MAJOR_ID", majorId));
    }

    @Override
    @Transactional(rollbackFor = RuntimeException.class)
    public void disableCompany(String companyIds) {
        List<String> companyIdList = findAllPathCompany(companyIds);
        //公司和子公司禁用
        metaService.executeSql("UPDATE JE_RBAC_COMPANY SET SY_STATUS='0' WHERE JE_RBAC_COMPANY_ID IN ({0})", companyIdList);
        //查找公司下所有的部门
        List<DynaBean> deptBeanList =  metaService.select("JE_RBAC_DEPARTMENT",ConditionsWrapper.builder().in("SY_COMPANY_ID",companyIdList));
        if(deptBeanList !=null && deptBeanList.size()>0){
            List<String> deptIdList = new ArrayList<>();
            for(DynaBean deptBean : deptBeanList){
                deptIdList.add(deptBean.getStr("JE_RBAC_DEPARTMENT_ID"));
            }
            //禁用人员，需判断人员部门主分关系，若该人员主部门属于该公司，则禁用所有；若人员分部门属于该公司，则只删除关联关系，不禁用人员。
            rbacDepartmentService.disableDepartments(StringUtils.join(deptIdList,","));
        }
    }

    @Override
    @Transactional(rollbackFor = RuntimeException.class)
    public void enableCompany(String companyIds) {
        List<String> companyIdList = Arrays.asList(companyIds.split(ArrayUtils.SPLIT));
        metaService.executeSql("UPDATE JE_RBAC_COMPANY SET SY_STATUS='1' WHERE JE_RBAC_COMPANY_ID IN ({0})",companyIdList);
    }

    @Override
    @Transactional(rollbackFor = RuntimeException.class)
    public long removeCompany(String companyIds, boolean withDeptAndUsers) {
        List<String> companyIdList = findAllPathCompany(companyIds);
        //同步删减公司表-监管公司字段该公司数据
        updateCompanyJgField(companyIds);

        int count = metaService.delete("JE_RBAC_COMPANY", ConditionsWrapper.builder().in("JE_RBAC_COMPANY_ID", companyIdList));
        if (!withDeptAndUsers) {
            return count;
        }
        //查找公司下所有的部门
        List<DynaBean> deptBeanList =  metaService.select("JE_RBAC_DEPARTMENT",ConditionsWrapper.builder().in("SY_COMPANY_ID",companyIdList));
        if(deptBeanList !=null && deptBeanList.size()>0){
            List<String> deptIdList = new ArrayList<>();
            for(DynaBean deptBean : deptBeanList){
                deptIdList.add(deptBean.getStr("JE_RBAC_DEPARTMENT_ID"));
            }
            //删除人员，需判断人员部门主分关系，若该人员主部门属于该公司，则删除所有；若人员分部门属于该公司，则只删除关联关系，不删除人员。
            rbacDepartmentService.removeDepartments(StringUtils.join(deptIdList,","), withDeptAndUsers);
        }
        return count;
    }

    /***
     * 全局同步更新去除该公司信息
     * @param companyIds
     */
    @Transactional(rollbackFor = RuntimeException.class)
    void updateCompanyJgField(String companyIds){
        List<Map<String, Object>> listCompanyBeanMap = findAllJGCompanyById(companyIds);
        List<String> idList = Splitter.on(",").splitToList(companyIds);
        for (Map<String, Object> eachBeanMap: listCompanyBeanMap) {
            //监管公司Id
            List<String> jgIdList = Arrays.asList(eachBeanMap.get("COMPANY_JGCOMPANY_ID").toString().split(ArrayUtils.SPLIT));
            List<String> newGgIdList = new ArrayList(jgIdList);
            List<String> indexData = new ArrayList<>();
            for(String companyId : idList){
                if(jgIdList.indexOf(companyId)>=0){
                    //记录要删除的下标
                    indexData.add(jgIdList.indexOf(companyId)+"");
                    newGgIdList.remove(companyId);
                }
            }
            //监管公司名称
            List<String> jgNameList = Arrays.asList(eachBeanMap.get("COMPANY_JGCOMPANY_NAME").toString().split(ArrayUtils.SPLIT));
            List<String> newGgNameList = new ArrayList(jgNameList);
            for(String eachIndex : indexData){
                newGgNameList.remove(Integer.parseInt(eachIndex));
            }
            metaService.executeSql("UPDATE JE_RBAC_COMPANY SET COMPANY_JGCOMPANY_ID={0},COMPANY_JGCOMPANY_NAME={1} WHERE JE_RBAC_COMPANY_ID={2} ",StringUtils.join(newGgIdList,","),StringUtils.join(newGgNameList,","),eachBeanMap.get("JE_RBAC_COMPANY_ID"));
        }
    }

    private List<Map<String, Object>> findAllJGCompanyById(String companyIds){
        //获取所有公司级子公司
        List<String> idList = Splitter.on(",").splitToList(companyIds);
        StringBuilder companySqlBuffer = new StringBuilder("SELECT * FROM JE_RBAC_COMPANY WHERE ");
        String[] params = new String[idList.size()];
        for (int i = 0; i < idList.size(); i++) {
            if (i == 0) {
                companySqlBuffer.append(" COMPANY_JGCOMPANY_ID LIKE {" + i + "}");
            } else {
                companySqlBuffer.append(" OR COMPANY_JGCOMPANY_ID LIKE {" + i + "}");
            }
            params[i] = "%"+ idList.get(i) + "%";
        }
        List<Map<String, Object>> companyBeans = metaService.selectSql(companySqlBuffer.toString(), params);
        return  companyBeans;
    }



    private List<String> findAllPathCompany(String companyIds) {
        //获取所有公司级子公司
        List<String> idList = Splitter.on(",").splitToList(companyIds);
        StringBuilder companySqlBuffer = new StringBuilder("SELECT * FROM JE_RBAC_COMPANY WHERE ");
        String[] params = new String[idList.size()];
        for (int i = 0; i < idList.size(); i++) {
            if (i == 0) {
                companySqlBuffer.append(" SY_PATH LIKE {" + i + "}");
            } else {
                companySqlBuffer.append(" OR SY_PATH LIKE {" + i + "}");
            }
            params[i] = "%"+ idList.get(i) + "%";
        }

        List<String> companyIdList = new ArrayList<>();
        List<Map<String, Object>> companyBeans = metaService.selectSql(companySqlBuffer.toString(), params);

        for (Map<String, Object> eachMap : companyBeans) {
            companyIdList.add((String) eachMap.get("JE_RBAC_COMPANY_ID"));
        }
        return companyIdList;
    }

    @Override
    public JSONTreeNode buildCompanyTree(String... companyIds) {
        JSONTreeNode rootNode = TreeUtil.buildRootNode();
        DynaBean table = beanService.getResourceTable("JE_RBAC_COMPANY");
        List<DynaBean> columns = (List<DynaBean>) table.get(BeanService.KEY_TABLE_COLUMNS);
        JSONTreeNode template = beanService.buildJSONTreeNodeTemplate(columns);

        List<DynaBean> allCompanyBeanList;
        if (companyIds == null || companyIds.length <= 0) {
            allCompanyBeanList = findAll();
        } else {
            List<String> allCompanyIdList = findAllPathCompany(Joiner.on(",").join(companyIds));
            allCompanyBeanList = metaService.select("JE_RBAC_COMPANY", ConditionsWrapper.builder()
                    .in("JE_RBAC_COMPANY_ID", allCompanyIdList).eq("SY_STATUS","1").apply("ORDER BY SY_TREEORDERINDEX ASC,SY_ORDERINDEX ASC"));
        }

        for (DynaBean eachBean : allCompanyBeanList) {
            if(companyIds == null || companyIds.length <= 0){
                if("ROOT".equals(eachBean.getStr("SY_PARENT"))){
                    JSONTreeNode node = buildTreeNode(template,rootNode.getId(),eachBean);
                    if (node != null) {
                        rootNode.getChildren().add(node);
                    }
                }
            }else {
                List<String> companyIdList = Arrays.asList(Joiner.on(",").join(companyIds).split(ArrayUtils.SPLIT));
                if(companyIdList.contains(eachBean.getStr("JE_RBAC_COMPANY_ID"))){
                    JSONTreeNode node = buildTreeNode(template,rootNode.getId(),eachBean);
                    if (node != null) {
                        rootNode.getChildren().add(node);
                    }
                }
            }
        }

        //递归形成树形结构
        for (JSONTreeNode eachNode : rootNode.getChildren()) {
            recursiveJsonTreeNode(template, eachNode, allCompanyBeanList);
        }

        return rootNode;
    }

    private void recursiveJsonTreeNode(JSONTreeNode template, JSONTreeNode rootNode, List<DynaBean> list) {
        if (list == null || list.isEmpty()) {
            return;
        }

        JSONTreeNode treeNode;
        for (DynaBean eachBean : list) {
            if(!Strings.isNullOrEmpty(rootNode.getId())  && !Strings.isNullOrEmpty(eachBean.getStr("SY_PARENT"))){
                if (rootNode.getId().equals(eachBean.getStr("SY_PARENT"))) {
                    treeNode = buildTreeNode(template, rootNode.getId(), eachBean);
                    rootNode.getChildren().add(treeNode);
                }
            }
        }

        if (rootNode.getChildren() == null || rootNode.getChildren().isEmpty()) {
            rootNode.setLeaf(true);
            return;
        }

        rootNode.setLeaf(false);

        for (JSONTreeNode eachNode : rootNode.getChildren()) {
            recursiveJsonTreeNode(template, eachNode, list);
        }

    }

    /**
     * 构建树形节点
     *
     * @param template     模板
     * @param parentNodeId 父节点ID
     * @param bean         当前bean
     * @return
     */
    private JSONTreeNode buildTreeNode(JSONTreeNode template, String parentNodeId, DynaBean bean) {
        JSONTreeNode node = new JSONTreeNode();
        node.setId(bean.getPkValue());
        node.setParent(parentNodeId);
        node.setLeaf(true);
        if (StringUtil.isNotEmpty(template.getText())) {
            node.setText(bean.getStr(template.getText()));
        }
        if (StringUtil.isNotEmpty(template.getCode())) {
            node.setCode(bean.getStr(template.getCode()));
        }
        //节点信息
        node.setNodeInfo(bean.getStr("COMPANY_CODE"));
        //节点信息类型
        node.setNodeInfoType("company");
        //节点类型
        if (StringUtil.isNotEmpty(template.getNodeType())) {
            node.setNodeType(bean.getStr(template.getNodeType()));
        }
        //节点路径
        if (StringUtil.isNotEmpty(template.getNodePath())) {
            node.setNodePath(bean.getStr(template.getNodePath()));
        }
        //是否禁用
        if (StringUtil.isNotEmpty(template.getDisabled())) {
            node.setDisabled(bean.getStr(template.getDisabled()));
        }
        //树形排序
        if (StringUtil.isNotEmpty(template.getTreeOrderIndex())) {
            node.setTreeOrderIndex(bean.getStr(template.getTreeOrderIndex()));
        }
        //节点类型
        if (StringUtil.isNotEmpty(template.getNodeType())) {
            node.setNodeType(bean.getStr(template.getNodeType()));
        }
        //图标样式
        if (StringUtil.isNotEmpty(template.getIcon())) {
            node.setIcon(bean.getStr(template.getIcon()));
        }
        //是否禁用
        if (StringUtil.isNotEmpty(template.getDisabled())) {
            node.setDisabled(bean.getStr(template.getDisabled()));
        } else {
            node.setDisabled("0");
        }
        //描述
        if (StringUtil.isNotEmpty(template.getDescription())) {
            node.setDescription(bean.getStr(template.getDescription()));
        }
        //排序
        if (StringUtil.isNotEmpty(template.getOrderIndex())) {
            node.setOrderIndex(bean.getStr(template.getOrderIndex()) + "");
        }
        node.setBean(bean.getValues());
        return node;
    }

}
